using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using dbpack;
using dbvc.data;
using dbvc.Queries;

namespace dbvc.Context
{
    internal static class ActivityRole
    {
        public static void Save(this db_activity self)
        {
            GenericQuery<db_activity>.Create(self);
        }
    }

    internal static class VesionRole
    {
        public static string GetCommaDelimitedString(this IEnumerable<db_version> versions)
        {
            return string.Join(", ", versions.Select(x => x.name).ToArray());
        }
    }

    public class CreatePackage
    {
        private db_project project;
        private db_user principal;
        private db_activity activity;
        
        private IList<db_version> versions;
        private IList<db_version> pversions;

        private IList<db_script> scripts;
        private IList<db_version_script> versions_scripts;

        private string fileName;
        
        private pack result = new pack { id = Guid.NewGuid() };

        public CreatePackage(int prjId, db_user principal, int[] verIds, string fileName)
        {
            this.principal = principal;
            this.fileName = fileName;

            //bind roles
            project = ProjectQuery.Get(prjId);
            versions = VersionQuery.GetVersions(verIds);
            pversions = VersionQuery.GetVersions(prjId);
            scripts = ScriptQuery.GetScripts(verIds);
            versions_scripts = ScriptQuery.GetVersionScripts(verIds);

            activity = new db_activity() { action = "generate update package", datestamp = DateTime.Now, userstamp = this.principal.name };
        }

        public void Execute()
        {
            var hash = InitHashesh();

            result.on_date = DateTime.Now.ToString("MM-dd-yyyy HH:mm");
            result.pack_versions = versions.GetCommaDelimitedString();
            result.project_versions = pversions.GetCommaDelimitedString();
            result.project = project.name;

            foreach (var v in versions)
            {
                var scripts = hash[v];

                var vv = new ver() {name = v.name};

                int k = 0;

                foreach (var s in scripts)
                {
                    var ss = new script() {name = s.name, body = s.text, sequence = ++k};

                    vv.scripts.Add(ss);
                }

                result.vers.Add(vv);
            }
            
            //serialize
            var serializer = new XmlSerializer(typeof (pack));
            using (var writeFileStream = new StreamWriter(fileName)){
                serializer.Serialize(writeFileStream, result);
            }

            //audit
            activity.Save();
        }

        private Dictionary<db_version, List<db_script>> InitHashesh()
        {
            var hVerScr = new Dictionary<db_version, List<db_script>>();

            var hVer = new Dictionary<int, db_version>();

            foreach (var ver in versions)
            {
                hVer.Add(ver.id, ver);
                hVerScr.Add(ver, new List<db_script>());
            }

            var hScr = scripts.ToDictionary(s => s.id);

            foreach (var vs in versions_scripts)
            {
                hVerScr[hVer[vs.id_version]].Add(hScr[vs.id_script]);
            }

            return hVerScr;
        }
    }
}